package cn.nr19.jian

import cn.nr19.jian.`object`.JianLeiApi
import cn.nr19.jian.token.EToken
import cn.nr19.jian.token.NumNode
import cn.nr19.jian.token.Token

object J2Utils {
    val cn_start = '\u4e00'.code
    val cn_end = '\u9fa5'.code

    /**
     * 输出
     */
    fun log(vararg t: Any?) {
        var tss = ""
        for (o in t) {
            if (o == null) continue
            if (o is Array<*>) {
                for (s in o) {
                    tss += ",$s"
                }
            } else {
                tss += ",$o"
            }
        }


        //DiaUtils.text(tss)
        // print("mlog,$tss\n")
        System.out.print("mlog:$tss\n")
    }

    /**
     * 找到下一个没有被转移的字符
     * @param a 欲讯号的
     * @param k 要寻找的值
     */
    fun indexOf(a:String,k : Char,start : Int = 0) : Int{
        var z = a.indexOf(k,start)
        if (z == 1) return z
        while (z != -1){

            // 判断上一个字符是否为转义符
            if (a.get(z-1).code == 92){
                var size = 1 // 转义符数量为单数 就相当于转义了本符号
                try {
                    while (a.get(z-size-1).code == 92){
                        size++
                    }
                }catch (e : Exception){
                    // 无视错误  一般就是出空了
                }

                // 双数，表示不转义这个符号
                if (size % 2 == 0){
                    return z
                }
            }else{
                return z
            }

            // 确定没问题就不会转啦
            z = a.indexOf(k,z + 1)
        }
        return z
    }

    /**
     * 代码中找，多个条件
     */
    fun indexOfCode(a:String,k : String,start : Int = 0) : Int{
        var z = a.indexOf(k,start)
        if (z == 1) return z
        while (z != -1){

            // 判断上一个字符是否为转义符
            if (a.get(z-1).code == 92){
                var size = 1 // 转义符数量为单数 就相当于转义了本符号
                try {
                    while (a.get(z-size-1).code == 92){
                        size++
                    }
                }catch (e : Exception){
                    // 无视错误  一般就是出空了
                }

                // 双数，表示不转义这个符号
                if (size % 2 == 0){
                    return z
                }
            }else{
                return z
            }

            // 确定没问题就不会转啦
            z = a.indexOf(k,z + 1)
        }
        return z
    }

    /**
     * 去转义符
     */
    fun delZy(a:String) : String{
        if (a.isEmpty()) return a
        val strs = StringBuilder()
        var endx = 0 // 上次截取的位置
        var pos = a.indexOf("\\",0)
        while (pos != -1){
            // 先截取
            strs.append(a.substring(endx,pos))
            endx = pos // 记录截取位置


            // 转义符下一个值
            try {
                when(a[pos + 1]){
                    '"' -> strs.append("\"")
                    '\'' -> strs.append("\'")
                    '\\' -> strs.append("\\")
                     '/' -> strs.append("/") // 沙币JSON 转义这个字符搞屁吃  操。
                    'n' -> strs.append("\n")
                    'r' -> strs.append("\r")
                    't' -> strs.append("\t")
                    'b' -> strs.append("\b")
                    else -> {
                        // throw ParserException("非法转义符 ${a[pos + 1]}",pos)
                        pos = a.indexOf("\\",pos+1) // 不管他 跳过就是
                        continue
                    }
                }
                endx = pos + 2 // 上面都是两字符转解码并接入到 strs 中
                pos = a.indexOf("\\",endx)
            }catch (e : StringIndexOutOfBoundsException){
                // 无视
                //e.printStackTrace()
                pos = -1
            }


        }

        // 剩余的
        strs.append(a.substring(endx))
        return strs.toString()
    }
    fun zy(a : String) : String{
        val strs = StringBuilder()
        a.forEach {
            when (it.code){
                // \n
                10 -> strs.append("\\n")
                13 -> strs.append("\\r")

                34 -> strs.append("\\\"") // 双引号
                39 -> strs.append("\\\'")  // 单引号 '
                92 -> strs.append("\\\\") // 转义符
                else -> strs.append(it)
            }
        }
        return strs.toString()
    }

    /**
     * @param d 双引号 或单引号。
     */
    fun delZy2(a:String,d : Boolean) : String{
        if (a.isEmpty()) return a
        val strs = StringBuilder()
        var endx = 0 // 上次截取的位置
        var pos = a.indexOf("\\",0)
        while (pos != -1){
            // 先截取
            strs.append(a.substring(endx,pos))
            endx = pos // 记录截取位置


            // 转义符下一个值
            try {
                when(a[pos + 1]){
                    '"' -> strs.append("\"")
                    '\'' -> strs.append("\'")
                    '\\' -> strs.append("\\")
                    '/' -> strs.append("/") // 沙币JSON 转义这个字符搞屁吃  操。
                    'n' -> strs.append("\n")
                    'r' -> strs.append("\r")
                    't' -> strs.append("\t")
                    'b' -> strs.append("\b")
                    else -> {
                        // throw ParserException("非法转义符 ${a[pos + 1]}",pos)
                        pos = a.indexOf("\\",pos+1) // 不管他 跳过就是
                        continue
                    }
                }
                endx = pos + 2 // 上面都是两字符转解码并接入到 strs 中
                pos = a.indexOf("\\",endx)
            }catch (e : StringIndexOutOfBoundsException){
                // 无视
                //e.printStackTrace()
                pos = -1
            }


        }

        // 剩余的
        strs.append(a.substring(endx))
        return strs.toString()
    }

    fun dnUnicode(encodeText : String) : String{
        fun decode1(unicode: String) = unicode.toInt(16).toChar()
        val unicodes = encodeText.split("\\u")
            .map { if (it.isNotBlank()) decode1(it) else null }.filterNotNull()
        return String(unicodes.toCharArray())
    }

    /**
     * 数据类型转换
     */
    fun int(any : Any?,def : Int):Int{
        if (any is Number) return any.toInt()
        else if (any is String) return any.toInt().let { if (it == 0) def else it }
        else if (any is NumNode) return any.value.toInt()
        else return def
    }
    fun float(any : Any?,def : Float):Float{
        if (any is Number) return any.toFloat()
        else if (any is String) return any.toFloat().let { if (it == 0f) def else it }
        else if (any is NumNode) return any.value.toFloat()
        else return def
    }
    fun toString(t: Any?):String{
        if (t is String) return  "\"${zy(t)}\""
        else return t.toString()
    }

    /**
     * 标准KEY
     */
    private val defTokenKeyMap = HashMap<Int,HashMap<String,EToken>>()
    fun tokens() : HashMap<Int,HashMap<String,EToken>>{
        if (defTokenKeyMap.size != 0) return defTokenKeyMap
        val tokenKeys = HashMap<String,EToken>()
        tokenKeys["真"] = EToken.TRUE
        tokenKeys["true"] = EToken.TRUE
        tokenKeys["TRUE"] = EToken.TRUE
        tokenKeys["假"] = EToken.FALSE
        tokenKeys["FALSE"] = EToken.FALSE
        tokenKeys["false"] = EToken.FALSE

        tokenKeys["变量"] = EToken.VAR
        tokenKeys["var"] = EToken.VAR

        tokenKeys["NULL"] = EToken.NULL
        tokenKeys["空"] = EToken.NULL

        tokenKeys["返回"] = EToken.RETURN
        tokenKeys["return"] = EToken.RETURN

        tokenKeys["跳过"] = EToken.CONTINUE
        tokenKeys["continue"] = EToken.CONTINUE

        tokenKeys["跳出循环"] = EToken.BREAK
        tokenKeys["跳出"] = EToken.BREAK
        tokenKeys["break"] = EToken.BREAK

        tokenKeys["则"] = EToken.start

        tokenKeys["若"] = EToken.IF
        tokenKeys["如果"] = EToken.IF
        tokenKeys["if"] = EToken.IF

        tokenKeys["否则"] = EToken.ELSE
        tokenKeys["else"] = EToken.ELSE

        tokenKeys["否则若"] = EToken.ElseIf
        tokenKeys["否则如果"] = EToken.ElseIf
        tokenKeys["则如果"] = EToken.ElseIf
        tokenKeys["则若"] = EToken.ElseIf
        tokenKeys["elseif"] = EToken.ElseIf


        tokenKeys["完毕"] = EToken.end
        tokenKeys["end"] = EToken.end

        tokenKeys["且"] = EToken.qie
        tokenKeys["或"] = EToken.huo

        tokenKeys["是"] = EToken.IS
        tokenKeys["is"] = EToken.IS
        tokenKeys["不是"] = EToken.NIS


        tokenKeys["变量"] = EToken.VAR
        tokenKeys["var"] = EToken.VAR

        tokenKeys["循环"] = EToken.FOR
        tokenKeys["for"] = EToken.FOR

        tokenKeys["until"] = EToken.FOR2
        tokenKeys["到"] = EToken.FOR2

        tokenKeys["判断"] = EToken.WHEN
        tokenKeys["when"] = EToken.WHEN

        tokenKeys["功能"] = EToken.FUN
        tokenKeys["fun"] = EToken.FUN

        tokenKeys["事件"] = EToken.EVENT
        tokenKeys["event"] = EToken.EVENT


        tokenKeys["继承"] = EToken.IN

        // 引用后面 有 KEY 作
        tokenKeys["引用"] = EToken.IMPORT
        tokenKeys["import"] = EToken.IMPORT

        tokenKeys.keys.forEach {
            (defTokenKeyMap[it.length] ?: HashMap()).let { it2->
                it2[it] = tokenKeys.get(it)!!
                defTokenKeyMap[it.length] = it2
            }
        }
        return defTokenKeyMap
    }
    private val eonTokenKeyMap = HashMap<Int,HashMap<String,EToken>>()

    fun eonTokens() : HashMap<Int,HashMap<String,EToken>>{
        if (eonTokenKeyMap.size != 0) return eonTokenKeyMap
        val tokenKeys = HashMap<String,EToken>()
        tokenKeys["真"] = EToken.TRUE
        tokenKeys["true"] = EToken.TRUE
        tokenKeys["TRUE"] = EToken.TRUE
        tokenKeys["假"] = EToken.FALSE
        tokenKeys["FALSE"] = EToken.FALSE
        tokenKeys["false"] = EToken.FALSE

        tokenKeys.keys.forEach {
            (eonTokenKeyMap[it.length] ?: HashMap()).let { it2->
                it2[it] = tokenKeys.get(it)!!
                eonTokenKeyMap[it.length] = it2
            }
        }
        return eonTokenKeyMap
    }

    fun pTokenType(token : Token){
        tokens().get(token.text.length)?.let {
            it.get(token.text)?.let {
                token.type = it
            }
        }
    }
    fun pTokenTypeEON(token : Token){
        eonTokens().get(token.text.length)?.let {
            it.get(token.text)?.let {
                token.type = it
            }
        }
    }

    /**
     * 是否为KEY
     */
    fun isKEYorNumber(str : String) : Boolean{
        if (str.isEmpty()) return false
        return str.matches(Regex("^[\\u4e00-\\u9fa5a-zA-Z0-9_]*$"))
    }
    /**
     * 是否为KEY
     */
    fun isKEY(str : String) : Boolean{
        if (str.isEmpty()) return false
        return str.matches(Regex("^[\\u4e00-\\u9fa5a-zA-Z_][\\u4e00-\\u9fa5a-zA-Z0-9_]*$"))
    }


    /**
     * @param cz 目标类
     */
    fun parserFun(cz : Any,name: String, pars: List<Any>) : Any?{
        val anys = ArrayList<Class<*>>()
        val datas = ArrayList<Any>()

        pars.forEach {
            val v = it
            when{
                v is Boolean -> anys.add(Boolean::class.java)
                v is String -> anys.add(String::class.java)
                v is Int -> anys.add(Int::class.java)
                v is Long -> anys.add(Int::class.java)
                v is Double -> anys.add(Double::class.java)
                v is Float -> anys.add(Float::class.java)
                v is JianLeiApi ->anys.add(JianLeiApi::class.java)
                else -> {
                    anys.add(v::class.java)
                }
            }
            datas.add(v)
        }
        try {
            // getDeclaredMethod // getMethod 本类
            return if (anys.isEmpty()) cz.javaClass.getMethod(name).invoke(cz) ?: ""
            else this.javaClass.getMethod(name,*anys.toTypedArray())
                .invoke(cz,*datas.toTypedArray()) ?: ""
        }
        catch (e : Exception){
            J2Utils.log("eeeee",name,anys,datas)
            return null
        }
    }

}